package org.example.thread.threadTest;

import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

/**
 * @Classname TicketPark
 * @Description park+自旋 锁
 * @Date 2021/3/24 9:56 上午
 * @Created by xiangjd
 */
public class TicketPark {
    //原子性
    private AtomicBoolean isLock = new AtomicBoolean(false);

    //票库存
    private int tickCount = 10;

    //等待线程队列
    private final Queue<Thread> WAIT_THREAD_QUEUE = new LinkedBlockingQueue<>();


    public void bye() {
        while (!lock()) {
           // Thread.yield(); 让出cpu,适合少量线程,如果线程过多的话,增加cpu的调度开销
           // Thread.sleep(1000); 让得不到锁的线程休息,不占用cpu资源
            lockwait();
        }
        String name = Thread.currentThread().getName();
        System.out.println(name + "加锁成功..");
        System.out.println(name + "开始抢票...");
        tickCount--;
        System.out.println(name + "抢票成功,余票还有" + tickCount);
        System.out.println(name + "释放锁..");
        unLock();
    }

    //释放锁
    public void unLock() {
        isLock.set(false);
        //唤醒队列中的第一个线程
        LockSupport.unpark(WAIT_THREAD_QUEUE.poll());
    }

    //加锁过程必须是原子性的,否则多线程会有线程安全问题
    public boolean lock() {
        return isLock.compareAndSet(false, true);
    }

    //将获取不到锁加入等待队列,并进行休眠
    public void lockwait() {
        WAIT_THREAD_QUEUE.add(Thread.currentThread());
        LockSupport.park();
    }
}
